package kubernetes

import (
	"errors"
	"fmt"

	"golang.org/x/net/context"
	v1 "k8s.io/api/core/v1"

	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var PodWrap podwrap = podwrap{}

type podwrap struct{}

func (podwrap) List(namespace string) (*v1.PodList, error) {
	return clientset.CoreV1().Pods(namespace).List(context.Background(), metav1.ListOptions{})
}

func (podwrap) Get(namespace, podname string) (*v1.Pod, error) {
	return clientset.CoreV1().Pods(namespace).Get(context.Background(), podname, metav1.GetOptions{})
}

func (podwrap) Delete(namespace, podname string) error {
	return clientset.CoreV1().Pods(namespace).Delete(context.Background(), podname, metav1.DeleteOptions{})
}

type podAssemble struct {
	namespace    string
	name         string
	image        string                  // 镜像
	envs         []v1.EnvVar             // 环境变量
	exposePorts  []v1.ContainerPort      // 端口expose
	volumeMounts []v1.VolumeMount        // 挂载
	volumes      []v1.Volume             // 挂载源
	Resources    v1.ResourceRequirements // 资源限制
}

func NewPodAssemble(namespace, name, imagename string) podAssemble {
	return podAssemble{namespace: namespace, name: name, image: imagename}
}

func (pa podAssemble) Create() (*v1.Pod, error) {
	if len(pa.name) == 0 || len(pa.namespace) == 0 || len(pa.image) == 0 {
		return nil, errors.New("还未填装pod")
	}
	selector := map[string]string{"name": pa.name}
	p := &v1.Pod{
		TypeMeta:   metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
		ObjectMeta: metav1.ObjectMeta{Namespace: pa.namespace, Name: pa.name, Labels: selector},
		Spec: v1.PodSpec{
			RestartPolicy: v1.RestartPolicyAlways,
			Volumes:       pa.volumes,
			Containers: []v1.Container{{
				Name:            pa.name,
				Image:           pa.image,
				ImagePullPolicy: v1.PullIfNotPresent,
				Ports:           pa.exposePorts,
				Env:             pa.envs,
				VolumeMounts:    pa.volumeMounts,
				Resources:       pa.Resources,
			}},
		},
	}
	return clientset.CoreV1().Pods(p.Namespace).Create(context.Background(), p, metav1.CreateOptions{})
}

func (pa podAssemble) EnvVar(name, value string) podAssemble {
	pa.envs = append(pa.envs, v1.EnvVar{Name: name, Value: value})
	return pa
}

func (pa podAssemble) Port(name string, containerPort int32) podAssemble {
	pa.exposePorts = append(pa.exposePorts, v1.ContainerPort{
		Protocol:      v1.ProtocolTCP,
		ContainerPort: containerPort,
		// HostPort:      containerPort,
	})
	return pa
}

// @param volumeMount 容器内挂载配置
// @param volume 外部挂载源
func (pa podAssemble) Volume(volumeMount v1.VolumeMount, volume v1.Volume) podAssemble {
	pa.volumeMounts = append(pa.volumeMounts, volumeMount)
	pa.volumes = append(pa.volumes, volume)
	return pa
}

func (pa podAssemble) Resource(cpu, mem int) podAssemble {
	pa.Resources = v1.ResourceRequirements{
		Limits: map[v1.ResourceName]resource.Quantity{
			v1.ResourceCPU:     resource.MustParse(fmt.Sprintf("%dm",cpu)), //m
			v1.ResourceMemory:  {}, //Mi
			v1.ResourceStorage: {}, //Gi
		},
	}
	return pa
}
